
#include "functions.h"

#define ADDFN0( name, func )\
    result = add_function2( r->eval, alloc_id(allocator, name, r->default_ns), func, false, r );\
    if( 0 == result ) { fprintf( stderr, "Can't add %s function!", #func ); return false; }

#define ADDFN1( name, func )\
    result = add_function2( r->eval, alloc_id(allocator, name, r->default_ns), func, true, r );\
    if( 0 == result ) { fprintf( stderr, "Can't add %s function!", #func ); return false; }

bool
add_rule_engine_functions( EvalContext * evaluator, RuleEngineContext * r )
{
    int             result;
    AllocContext *  allocator = r->alloc_ctx;

    r->eval = evaluator;

    initialize_vars( r );
    
    ADDFN0( "def-static-rules", f_def_static_rules );
    ADDFN0( "dsr", f_def_static_rules );

    ADDFN0( "match", f_match );

    ADDFN0( "def-dynamic-rule", f_def_dynamic_rule );
    ADDFN0( "ddr", f_def_dynamic_rule );
    ADDFN0( "get-dynamic-rule", f_get_dynamic_rule );
    ADDFN0( "gdr", f_get_dynamic_rule );
    ADDFN0( "apply-dynamic-rule", f_apply_dynamic_rule );
    ADDFN0( "adr", f_apply_dynamic_rule );

    ADDFN0( "get-static-rules", f_get_static_rules );
    ADDFN0( "gsr", f_get_static_rules );

    // logic
    ADDFN0( "if", f_if );
    ADDFN0( "cond", f_cond );
    ADDFN1( "==", f_eq );
    ADDFN1( ">", f_greater );
    ADDFN1( "<", f_less );
    ADDFN1( ">=", f_greater_or_equal );
    ADDFN1( "<=", f_less_or_equal );

    ADDFN1( "load", f_load );

    ADDFN0( "set-namespace", f_set_namespace );
    ADDFN0( "get-namespace", f_get_namespace );

    ADDFN0( "setf", f_setvar );

    ADDFN1( "print", f_print );

    ADDFN0( "quit", f_quit );
    ADDFN0( "q", f_quit );

    ADDFN0( "progn", f_progn );

    return true;
}

void initialize_functions( RuleEngineContext * r )
{
    r->static_rules = alloc_list( r->alloc_ctx );
    r->dynamic_rules = alloc_list( r->alloc_ctx );

    add_predefined_relations( r );
}




static void
free_relation_traits_cb( void * tag, Obj * node )
{
    ql_free( node );
}

void free_functions( RuleEngineContext * r )
{
}
